global class BatchtoretrofitOppEDC implements Database.Batchable<SObject>,Database.Stateful{

    public String querystring;
    public Map<String,EDC_for_opportunity__c> edcsettingmap;
    global Database.QueryLocator start(Database.BatchableContext BC){
            querystring='select id,CloseDate,Upper_EDC__c,Project_Name__c,Date_of_Visit__c,Last_Call_Date_RO__c from Opportunity';
            return Database.getQueryLocator(querystring);
        }
        
        global void execute(Database.BatchableContext BC, List<sObject> sobjectlist){
          List<Opportunity> opportunityupdatelist=new List<Opportunity>();
          
          List<EDC_for_opportunity__c> edcvolist=[select id,Project_Type__c,EDC_from_Created_date__c,EDC_from_Visit_date__c,Upper_Limit__c,Call_Attempt_Limit__c,
            Call_Attempt_EDC__c from EDC_for_opportunity__c];
   
            Map<id,Project_Name__c>  projectmap=new Map<id,Project_Name__c>([select id,Project_Type__c from Project_Name__c]);        
            
            edcsettingmap=new Map<String,EDC_for_opportunity__c>();
            for(EDC_for_opportunity__c edcvalue: edcvolist){
                edcsettingmap.put(edcvalue.Project_Type__c,edcvalue);            
            }
            
            for(sObject sobj: sobjectlist){         
                Opportunity opp=(Opportunity)sobj;
                String projecttype=projectmap.get(opp.Project_Name__c).Project_Type__c;
                Integer edcfromcreateddate=Integer.valueof(edcsettingmap.get(projecttype).EDC_from_Created_date__c); 
                Integer edcfromvisitddate=Integer.valueof(edcsettingmap.get(projecttype).EDC_from_Visit_date__c); 
                Integer upperedc=Integer.valueof(edcsettingmap.get(projecttype).Upper_Limit__c);
                Integer callattemptlimit=Integer.valueof(edcsettingmap.get(projecttype).Call_Attempt_Limit__c);
                Integer callattemptedc=Integer.valueof(edcsettingmap.get(projecttype).Call_Attempt_EDC__c);
                
               opp.IsActive__c=true;           
                if(opp.Date_of_Visit__c==null){                                                                                                                                 
                    opp.Closedate=system.today().adddays(edcfromcreateddate); 
                    opp.Upper_EDC__c=System.Today().addDays(upperedc);
                    opp.Current_EDC__c=opp.CloseDate;               
                }else{
                    Date dovlimit= date.parse('01/06/2012');                    
                    if(opp.Date_of_Visit__c>=dovlimit){
                        opp.Closedate=system.today().adddays(edcfromvisitddate); 
                        opp.Upper_EDC__c=System.Today().addDays(upperedc);
                        opp.Current_EDC__c=opp.CloseDate;                    
                    }else{
                        opp.Closedate=opp.Date_of_Visit__c.adddays(edcfromvisitddate); 
                        opp.Upper_EDC__c=opp.Date_of_Visit__c.addDays(upperedc);
                        opp.Current_EDC__c=opp.CloseDate; 
                    
                    }
                
                } 

               if(opp.Last_Call_Date_RO__c!=null){

                    Integer differenceindays=(opp.Last_Call_Date_RO__c.date()).daysBetween(opp.CloseDate);
                    
                    Date lastcalldate=opp.Last_Call_Date_RO__c.date();
                    String oppid=opp.id;
                    
                    List<Call_Attempts__c > callattemptlist=[select id,Createddate,Proposed_Date_of_Visit__c,Call_Attempt_Status__c from Call_Attempts__c where DAY_ONLY(Createddate)=:lastcalldate AND Opportunity__c=:oppid];

                    for(Call_Attempts__c callattempt: callattemptlist){


                        if((differenceindays<=callattemptlimit)&&(callattempt.Call_Attempt_Status__c=='Visit Confirmed'||callattempt.Call_Attempt_Status__c=='Visit Proposed')){
                            opp.CloseDate=callattempt.Proposed_Date_of_Visit__c.date().addDays(callattemptedc);
                             opp.Current_EDC__c=opp.CloseDate;   
                
                        }
                             if(opp.CloseDate>opp.Upper_EDC__c){
                                 opp.Upper_EDC__c=callattempt.Proposed_Date_of_Visit__c.date().addDays(callattemptedc);  
                             }
                    
                    }

                }  
                opportunityupdatelist.add(opp);                                                    
            }
        
            update opportunityupdatelist;
        }
        
        global void finish(Database.BatchableContext BC){
        
       }

}